from django.contrib.auth import logout
from django.db.models import Sum, F
from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
# Create your views here.
from myApp.models import Grade, Student, IdCard, Person, Product, Buyer

# 缓存:
from django.views.decorators.cache import cache_page   # 缓存
@cache_page(60*1)
def index(request):
    # return render(request, "index.html")
    # return HttpResponse("first")
    return HttpResponse("second")
# def marketRef(request):
#     return HttpResponse("this is httpresponse")
def marketRef(request, num):
    return HttpResponse("this is httpresponse%s"%num)

def detail(request, num):
    return HttpResponse("detail %s"%num)

def student(request):
    # 获取所有学生信息列表
    try:
        # students  = [Student.objects.get(pk=2)]
        # students  = Student.objects.all()[0:5]
        # students  = Student.objects.all().filter(age__lte=20)
        # students  = Student.objects.all().filter(name__contains="ping")
        # students  = Student.objects.all().filter(pk__in =[1,2,3,4,5])
        # students  = Student.objects.all().filter(grade_id=1)
        # age = Student.objects.aggregate(Sum("age"))
        # print(age)
        grades = Grade.objects.filter(boyNum__lt=F("girlNum"))
        print(grades)

        students  = Student.objects.all().filter()
    except Student.DoesNotExist as e:
        pass
    except Student.MultipleObjectsReturned as e:
        pass
    # print(students)
    year = 2019
    return render(request, 'students.html',{"studentList":students,"year":year})

def grade(request):
    grades =Grade.objects.all()
    return render(request, 'grades.html',{"gradeList":grades})

def gradeByStudent(request, gid):
    # gradeId = Grade.objects.get(pk=gid)
    # students = Student.objects.filter(grade=gradeId)
    students = Student.objects.filter(grade_id=gid)
    return render(request, "students.html",{"studentList":students})


def addStudent(request):
    # addStu = Student()
    # addStu.name = "张珊"
    # addStu.sex = True
    # addStu.age = 18
    # addStu.content = " zhangshan is a nicegirl"
    # addStu.grade = Grade.objects.get(pk =1)
    # addStu.save()
    # return HttpResponse("增加学生成功")
    addStu = Student.create("zhangshan", True, 18, " zhangshan is a nicegirl",
                            Grade.objects.get(pk =1))
    addStu.save()
    return HttpResponse("增加学生成功")


def addIdcard(request, num):
    idCard = IdCard()
    idCard.sex = True
    idCard.num = num
    idCard.save()
    return  HttpResponse("create IdCard success")

def addPerson(request, id):
    person = Person()
    person.name = "zhu"
    person.age = 25
    person.idCard = IdCard.objects.get(pk= id)
    person.save()
    return  HttpResponse("create Person success")


def delIdCard(request,id):
    card=  IdCard.objects.get(id =id)
    card.delete()
    return HttpResponse("delete idCard success")

def delPerson(request,id):
    person=  Person.objects.get(id =id)
    person.delete()
    return HttpResponse("delete person success")


def findPerson(request,id):
    # per = Person.objects.get(pk= id)
    # print(per.idCard.num)
    # idCard = IdCard.objects.get(pk= id)
    # print(idCard.person.name)
    # grade  = Grade.objects.get(pk= id)
    # print(grade.student_set.all())
    # product = Product.objects.get(pk=id)
    # print(product.buyers)
    buyers = Buyer.objects.get(pk =id)
    print(buyers.product_set.all())
    return HttpResponse("all buyers ")


def addProduct(request,name, price):
    product = Product()
    product.name = name
    product.price = price
    product.save()
    return HttpResponse("product create success")

def addBuyer(request, name, lebel):
    buyer = Buyer()
    buyer.name = name
    buyer.lebel = lebel
    buyer.save()
    return HttpResponse("buyer create success")

def pTob(request, product, buyer):
    product = Product.objects.get(name = product)
    buyer = Buyer.objects.get(name = buyer)
    # 产生关联
    product.buyers.add(buyer)
    return HttpResponse("add buyer success")


def test(request, num):
    print(request.path)
    print(request.method)
    print(request.encoding)
    print(request.GET)
    print(request.POST)
    print(request.FILES)
    print(request.COOKIES)
    print(request.session)
    return render(request, "test.html", {"num":num})

def get1(request):
    a = request.GET.get("a")
    b = request.GET.get("b")
    c = request.GET.get("c")
    return HttpResponse(a + b + c)

def get2(request):
    alist = request.GET.getlist("a")
    c = request.GET.get("c")
    return HttpResponse(alist[0]+ alist[1] + c)

def testRegiste(request):
    if request.method == "GET":
        return render(request, "testRegiste.html")
    else:
        username = request.POST.get("username")
        password = request.POST.get("passwd")
        hobby = request.POST.getlist("hobby")
        print(username,password,hobby)
        return HttpResponse("registe success")


def originRedirectLogin(request):
    # return HttpResponseRedirect("test")
    # return redirect("/test")
    # return redirect("/loginPage")
    return redirect("/upfile")


def homeFunc(request):
    userAccount = request.session.get("userAccount",default = "未登录")
    return render(request, "homePage.html", {"userAccount":userAccount})
def homeChildFunc(request):
    userAccount = request.session.get("userAccount",default = "未登录")
    return render(request, "homeChiledPage.html", {"userAccount":userAccount})

def loginFunc(request):
    if request.method == "GET":
        fromPath = request.GET.get("from")
        infoStr = "<h1>登陆首页</h1>"
        infoStr2 = "<script>alert('登陆首页')</script>"
        return render(request, "login.html", {"fromPath":fromPath,
                                              "infoStr":infoStr,"infoStr2":infoStr2})
    elif request.method == "POST":
        # 验证码 ( 注释以下3行是因为重新在中间件中已经写了)
        # verifycode = request.POST.get("verifycode")
        # if not verifycode.upper() == request.session.get("verifycode_session").upper():
        #     return redirect("/loginPage")

        userAccount = request.POST.get("userAccount")
        password = request.POST.get("password")
        fromPath = "/" + request.GET.get("from") + "/"
        if userAccount == "zyp" and password == "123":
            # success
            # 状态保持, 将用户名写入session
            request.session["userAccount"] = userAccount
            # return HttpResponse("success")
            if fromPath == "/None/":   # 起始网页就是loginPage, 没有从其他地方跳转过来
                return redirect("/homePage")
            return redirect(fromPath+"?from=loginPage")
        else:
            # failed
            fromPath = request.GET.get("from")
            return redirect('/loginPage/?from=%s'%fromPath)

def logoutFunc(request):
    logout(request)
    return redirect("/homePage")


# 继承 base
def child1(request):
    return render(request,"child1.html")
def child2(request):
    return render(request,"child2.html")
def child3(request):
    return render(request,"child3.html")


# 验证码
def verifycodeFunc(request):
        # 引入绘图模块
        from PIL import Image, ImageDraw, ImageFont
        # 引入随机函数模块
        import random
        # 定义变量，用于画面的背景色、宽、高
        bgcolor = (random.randrange(20, 100), random.randrange(20, 100), random.randrange(20, 100))
        width = 100
        height = 50
        # 创建画面对象
        im = Image.new('RGB', (width, height), bgcolor)
        # 创建画笔对象
        draw = ImageDraw.Draw(im)
        # 调用画笔的point()函数绘制噪点
        for i in range(0, 10):
            xy = (random.randrange(0, width), random.randrange(0, height))
            fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
            draw.point(xy, fill=fill)
        # 定义验证码的备选值
        str = '1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'
        # 随机选取4个值作为验证码
        rand_str = ''
        for i in range(0, 4):
            rand_str += str[random.randrange(0, len(str))]
        # 构造字体对象
        font = ImageFont.truetype(r'D:\project\static\consola.ttf', 40)
        # 构造字体颜色
        fontcolor1 = (255, random.randrange(0, 255), random.randrange(0, 255))
        fontcolor2 = (255, random.randrange(0, 255), random.randrange(0, 255))
        fontcolor3 = (255, random.randrange(0, 255), random.randrange(0, 255))
        fontcolor4 = (255, random.randrange(0, 255), random.randrange(0, 255))
        # 绘制4个字
        draw.text((5, 2), rand_str[0], font=font, fill=fontcolor1)
        draw.text((25, 2), rand_str[1], font=font, fill=fontcolor2)
        draw.text((50, 2), rand_str[2], font=font, fill=fontcolor3)
        draw.text((75, 2), rand_str[3], font=font, fill=fontcolor4)
        # 释放画笔
        del draw
        # 存入session，用于做进一步验证
        request.session['verifycode_session'] = rand_str
        # 内存文件操作
        import io
        buf = io.BytesIO()
        # 将图片保存在内存中，文件类型为png
        im.save(buf, 'png')
        # 将内存中的图片数据返回给客户端，MIME类型为图片png
        return HttpResponse(buf.getvalue(), 'image/png')

from django.conf import settings
def upfileFunc(request):
    if request.method == "GET":
        return render(request, "upfile.html")
    else:
        for strDiffFile in request.FILES:
            lstFiles = request.FILES.getlist(strDiffFile)
            print(lstFiles)
            for strfile in lstFiles:
                # 处理每个文件
                filePath = r"%s\%s"%(settings.MEDIA_ROOT,strfile.name)
                # 将文件数据切片写入描述符
                with open(filePath,"wb") as fp:
                    for filePart in strfile.chunks():
                        fp.write(filePart)
        return HttpResponse("upfiles ok")

    # 分页器
from django.core.paginator import Paginator
def pageStudentFunc(request,pageNum):
    allStudents = Student.objects.all()
    # 分页
    paginator = Paginator(allStudents, 6)
    pageStudentList = paginator.page(pageNum)
    print(paginator.count, paginator.num_pages, paginator.page_range)
    print(pageStudentList.object_list, pageStudentList.number, pageStudentList.paginator)
    # print(pageStudentList.paginator.)
    return render(request, "students.html",{"studentList":pageStudentList})

# ajax
def ajax_allStudentFunc(request):
    if request.method == "GET":
        # 如果是ajax 请求
        if not request.is_ajax():
            return render(request,   "ajax_allStudents.html")
        # 如果不是ajax请求:
        else:
            students = Student.objects.all()
            getList = []
            for stu in students:
                getList.append({"name":stu.name, "age":stu.age})
            # return JsonResponse({"data":"this is jsonResponse"})
            return JsonResponse({"data":getList})

#  富文本
def tinymce(request):
    if request.method == "GET":
        return render(request, "tinymce.html")
    else:
        pass

#  celery
# def celeryRegister(request):
    # import time
    # print("time delay")
    # time.sleep(3)
    # print("time past")
    # return HttpResponse('test celery')
from myApp.task import LongIO
def celeryRegister(request):
    LongIO.delay()
    return HttpResponse("test celery")
#  cmd : python manage.py celery worker --loglevel=info

# sendEmail
from django.conf import settings
from django.core.mail import send_mail
def sendEmailFunc(request):
    # user = User.create()
    # user.save()
    msg = "<a href='http://www.baidu.com'>click to motivate</a>"
    send_mail("注册激活","",settings.EMAIL_FROM,
              ["15779786901@163.com"],html_message=msg)
    request.session["userAccount"] = "zypdominate1"
    return HttpResponse("send Email success")

def checkUser(request):
    # userAccount = request.session.get("userAccount")
    # user = User.objects.get(pk = userAccount)
    # user.active = True
    # user.save()
    return None


# ----------------------------restful-------------------------------------------------
from myApp.serializers import StudentSerializer
from rest_framework.renderers import JSONRenderer
from django.utils.six import BytesIO
from rest_framework.parsers import JSONParser

def studentsList(request):
    if request.method == "GET":
        stus = Student.objects.all()
        #  序列化
        serializer =  StudentSerializer(stus, many=True)
        return JsonResponse(serializer.data, safe=False)
    elif request.method == "POST":
        # 把前端传过来的数据转为 json数据
        content = JSONRenderer().render(request.POST)
        stream = BytesIO(content)
        stuDict = JSONParser().parse(stream)
        serializer = StudentSerializer(data=stuDict)  # 不用一个一个地传 字段
        if serializer.is_valid():
            # 数据没有问题就保存数据, 并返回状态码 201(POST)
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse({"error": serializer.errors})

def studentsListDetail(request, pk):
    try:
        stu = Student.objects.get(pk= pk)
    except Student.DoesNotExist as e:
        return JsonResponse({"error":str(e)}, status=404)

    if request.method == "GET":
        serializer = StudentSerializer(stu)
        return JsonResponse(serializer.data)

    elif request.method == "PUT":
        print(request.POST)
        content = JSONRenderer().render(request.POST)
        stream = BytesIO(content)
        stuDict = JSONParser().parse(stream)
        # 修改
        serializer = StudentSerializer(stu, data=stuDict)
        # serializer = StudentSerializer(data=stuDict)   # 与POST的区别
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse({"error":serializer.errors}, status=400)
    elif request.method == "DELETE":
        stu.delete()
        # return JsonResponse(data=stu, status= 204)
        return HttpResponse(status= 204, content_type="application/json")

    return None

# restful 的请求和响应
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response

@api_view(["GET", "POST"])
# def studentsListReqRes(request):
def studentsListReqRes(request, format = None):  # 可以在url后面增加后缀 .api
    if request.method == "GET":
        stus = Student.objects.all()
        #  序列化
        serializer =  StudentSerializer(stus, many=True)
        # 不需要指定json格式, 返回客户端可以返回json或者html
        # 返回html内容的话, 会在浏览器总经过渲染成页面
        return Response(serializer.data, status=status.HTTP_200_OK)
    elif request.method == "POST":
        serializer = StudentSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response({"error": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)

@api_view(["GET", "PUT", "DELETE"])
# def studentsListDetailReqRes(request, pk):
def studentsListDetailReqRes(request, pk, format=None):  # 可在 url后面增加 后缀 .api
    try:
        stu = Student.objects.get(pk= pk)
    except Student.DoesNotExist as e:
        return Response({"error":str(e)}, status=status.HTTP_404_NOT_FOUND)

    if request.method == "GET":
        serializer = StudentSerializer(stu)
        return Response(serializer.data)

    elif request.method == "PUT":
        # 修改
        serializer = StudentSerializer(stu, data=request.data)
        # serializer = StudentSerializer(data=stuDict)   # 与POST的区别
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response({"error":serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
    elif request.method == "DELETE":
        stu.delete()
        return Response(status= status.HTTP_204_NO_CONTENT)
    return None


# 类视图
#  使用 类视图, 比使用函数的效率更高, 函数里面无需再判断
from rest_framework.views import APIView
from django.http import Http404

class StudentsListClass(APIView):
    def get(self, request, format=None):
        stus = Student.objects.all()
        serializer = StudentSerializer(stus, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)
    def post(self, request, format=None):
        serializer = StudentSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response({"error":serializer.errors})


class StudentsListDetailClass(APIView):
    def getObject(self, pk):
        try:
            return Student.objects.get(pk=pk)
        except Student.DoesNotExist as e:
            raise Http404
    def get(self, request, pk, format=None):
        stu = self.getObject(pk)
        serializer = StudentSerializer(stu)
        return Response(serializer.data)
    def put(self, request, pk, format=None):
        stu = self.getObject(pk)
        serializer = StudentSerializer(stu, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
    def delete(self, request, pk, format=None):
        stu = self.getObject(pk=pk)
        stu.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


# 使用 mixins, generics 优化后的类视图
from rest_framework import mixins, generics
# 父类中有且只有一个能继承APIView类
class StudentListMixin(mixins.ListModelMixin, mixins.CreateModelMixin,
                       generics.GenericAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)
    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

class StudentListDetailMixin(mixins.RetrieveModelMixin, mixins.UpdateModelMixin,
                             mixins.DestroyModelMixin, generics.GenericAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)
    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)
    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)


#  究极继承:   ----> 不推荐使用
# from rest_framework import generics
class StudentsListSimplied(generics.ListAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
class StudentListDetailSimplied(generics.RetrieveAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer




